package com.youxin.chat.user.manager;

import com.alibaba.fastjson.JSONObject;
import com.alicp.jetcache.anno.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.youxin.chat.user.enums.UserRedisKey;
import com.youxin.chat.user.mapper.ActiveUserMapper;
import com.youxin.chat.user.mapper.UserDeviceMapper;
import com.youxin.chat.user.mapper.UserInfoMapper;
import com.youxin.chat.user.model.ActiveUser;
import com.youxin.chat.user.model.UserDevice;
import com.youxin.chat.user.model.UserInfo;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * description: UserManager <br>
 * date: 2020/3/11 2:00 <br>
 * author: llkj <br>
 * version: 1.0 <br>
 */
@Service
public class UserManager {

    @Resource
    private UserDeviceMapper userDeviceMapper;

    @Resource
    private UserInfoMapper userInfoMapper;

    @Resource
    private ActiveUserMapper activeUserMapper;

    @Cached(name="userInfoCache.", key="#userNo",expire = 1,timeUnit = TimeUnit.DAYS,cacheNullValue=false)
    @CacheRefresh(refresh = 30,timeUnit = TimeUnit.MINUTES)
    public UserInfo selectByUserNo(String userNo){
        UserInfo userInfo = userInfoMapper.selectByUserNo(userNo);
        return userInfo;
    }

    @CacheInvalidate(name="userInfoCache.", key="#userInfo.userNo")
    public void insertUserInfo(UserInfo userInfo){
        userInfoMapper.insert(userInfo);
    }

    @CacheInvalidate(name="userInfoCache.", key="#userInfo.userNo")
    public void updateUserInfo(UserInfo userInfo){
        userInfoMapper.updateById(userInfo);
    }

    @Cached(name="userDevice.", key="#userNo",expire = 1,timeUnit = TimeUnit.DAYS)
    @CacheRefresh(refresh = 1,timeUnit = TimeUnit.HOURS)
    public UserDevice selectActiveByUserNo(String userNo){
       return userDeviceMapper.selectActiveByUserNo(userNo);
    }

    @CacheInvalidate(name = "userDevice.",key = "#userDevice.userNo")
    public void saveUserDevice(UserDevice userDevice){
        if (StringUtils.isEmpty(userDevice.getId())) {
            userDeviceMapper.insert(userDevice);
        } else {
            userDeviceMapper.updateById(userDevice);
        }
    }

    @Cached(name="userDeviceByToken.", key="#token",cacheType = CacheType.BOTH,expire = 1,timeUnit = TimeUnit.DAYS)
    @CacheRefresh(refresh = 1,timeUnit = TimeUnit.HOURS)
    public UserDevice selectByAccessToken(String token){
        return userDeviceMapper.selectByAccessToken(token);
    }

    @Cached(name="specialUserCache", key = "1",expire = 2,timeUnit = TimeUnit.DAYS)
    @CacheRefresh(refresh = 1,timeUnit = TimeUnit.HOURS)
    public List<UserInfo> listSpecialUsers(){
        List<UserInfo> list =  userInfoMapper.selectList(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getUserType,1));
        return list;
    }

    @CacheInvalidate(name = "specialUserCache",key = "1")
    public void saveUser(UserInfo userInfo){
        if(StringUtils.isEmpty(userInfo.getId())){
            userInfoMapper.insert(userInfo);
        }else{
            userInfoMapper.updateById(userInfo);
        }
    }

    @Async
    public void saveActiveRecord(String userNo) {
        ActiveUser activeUser = new ActiveUser();
        activeUser.setUserNo(userNo);
        activeUser.setUseDate(LocalDate.now().atStartOfDay());
        activeUser.setCreateTime(LocalDateTime.now());
        LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<ActiveUser>()
                .eq(ActiveUser::getUserNo, activeUser.getUserNo())
                .eq(ActiveUser::getUseDate, activeUser.getUseDate());
        int count = activeUserMapper.selectCount(queryWrapper);
        if (count == 0) {
            activeUserMapper.insert(activeUser);
            userInfoMapper.updateUseTimeByUserNo(activeUser.getUseDate(), activeUser.getUserNo());
            return;
        }
    }
}
